import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import routes from './systemRouter'
import { beforeEach, afterEach } from './scrollBehavior'
// 扩展 Router 类型，添加 get_menu 方法
declare module 'vue-router' {
	interface Router {
		sc_getMenu: () => RouteRecordRaw[]
	}
}
// 用户路由
const userRoutes: RouteRecordRaw[] = []
// 动态引入 views 目录下的 Vue 组件
const modules = import.meta.glob('../views/**/**.vue')
// 系统404路由
const routes_404: RouteRecordRaw = {
	// 匹配所有未定义的路径
	path: '/:pathMatch(.*)*',
	// 引入404组件
	component: () => import('../layout/other/404.vue')
}
// 用于存储404路由的返回值
let routes_404_r: ReturnType<typeof router.addRoute> | undefined
// 创建路由实例
const router = createRouter({
	history: createWebHashHistory(),
	routes
})
// 判断是否已加载过动态/静态路由
let isGetRouter = false
// 配置进度条
NProgress.configure({ showSpinner: false })
// 路由守卫
router.beforeEach(async (to, from, next) => {
	// 开始进度条
	NProgress.start()
	// 获取系统存储实例
	const systemStore = useSystemStore()
	// 监听站点标题的变化
	watchEffect(() => {
		if (systemStore.website.name) {
			// 设置页面标题
			document.title = to.meta.title ? `${to.meta.title} - ${systemStore.website.name}` : `${systemStore.website.name}`
		}
	})
	// 获取存储的 token
	const token = tool.cookie.get('token')
	// 处理登录路由
	if (to.path === '/login') {
		// 添加初始路由
		router.addRoute(routes[0])
		// 删除404路由
		routes_404_r?.()
		// 重置路由状态
		isGetRouter = false
		// 若已登录则直接跳转
		if (token) {
			next({ path: '/' })
		} else {
			next()
		}
		return
	}
	// 检查目标路由是否在静态路由中
	if (routes.some((route) => route.path === to.path)) {
		// 如果匹配，继续导航
		next()
		return
	}
	// 如果没有 token，重定向到登录页面
	if (!token) {
		next({ path: '/login' })
		return
	}
	// 检查是否已经加载过动态路由
	if (!isGetRouter) {
		// 加载用户路由
		const menu = loadUserRoutes()
		// 过滤并处理异步路由
		let menuRouter = filterAsyncRouter(menu)
		// 扁平化路由结构
		menuRouter = flatAsyncRoutes(menuRouter)
		// 添加用户路由到 layout
		menuRouter.forEach((item) => {
			router.addRoute('layout', item)
		})
		routes_404_r = router.addRoute(routes_404)
		// 如果没有匹配到路由，重定向到完整路径
		if (to.matched.length === 0) {
			router.push(to.fullPath)
		}
		// 标记路由已加载
		isGetRouter = true
	}
	// 调用自定义的前置守卫
	beforeEach(to, from)
	// 继续导航
	next()
})
// 后置守卫
router.afterEach((to, from) => {
	// 调用自定义的后置守卫
	afterEach(to, from)
	// 完成进度条
	NProgress.done()
})
// 错误提醒
router.onError((error) => {
	// 在发生错误时完成进度条
	NProgress.done()
	// 显示错误通知
	ElNotification.error({
		title: lang.global.t('common.routeError'),
		message: error.message
	})
})
// 添加获取用户菜单的方法
router.sc_getMenu = () => loadUserRoutes()
/**
 * 加载用户可访问的路由
 * @returns {any[]} 用户路由数据
 */
const loadUserRoutes = () => {
	// 获取菜单数据
	const apiMenu = tool.data.get('MENU') || []
	// 获取用户信息
	const userInfo = tool.data.get('USER_INFO')
	// 过滤用户可访问的路由
	const userMenu = treeFilter(userRoutes, (node: any) => {
		return node.meta.role ? node.meta.role.filter((item: any) => userInfo.role.indexOf(item) > -1).length > 0 : true
	})
	// 返回合并菜单
	return [...userMenu, ...apiMenu]
}
/**
 * 过滤树形结构，获取可访问的节点
 * @param {any[]} tree - 树形结构
 * @param {any} func - 过滤函数
 * @returns {any[]} 可访问的节点
 */
function treeFilter(tree: any[], func: any): any[] {
	return tree.filter((node) => {
		node.children = node.children && treeFilter(node.children, func)
		return func(node) || (node.children && node.children.length)
	})
}
/**
 * 过滤并处理异步路由
 * @param {any[]} routerMap - 路由配置映射表
 * @returns {any[]} 处理后的路由数组
 */
function filterAsyncRouter(routerMap: any[]): any[] {
	return routerMap.map((item) => {
		// 处理外部链接特殊路由
		if (item.meta?.type === 'iframe') {
			item.meta.url = item.path
			item.path = `/i/${String(item.name)}`
		}
		// 构建路由对象
		const route: any = {
			path: item.path,
			name: item.name,
			meta: item.meta,
			redirect: item.redirect,
			children: item.children ? filterAsyncRouter(item.children) : null,
			component: loadComponent(item.component)
		}
		return route // 返回处理后的路由对象
	})
}
/**
 * 扁平化异步路由，并添加面包屑信息
 * @param {RouteRecordRaw[]} routes - 路由数组
 * @param {RouteRecordRaw[]} breadcrumb - 面包屑路径数组
 * @returns {RouteRecordRaw[]} - 扁平化的路由数组
 */
function flatAsyncRoutes(routes: RouteRecordRaw[], breadcrumb: any[] = []): RouteRecordRaw[] {
	let res: any[] = []
	routes.forEach((route) => {
		const tmp = { ...route }
		if (tmp.children) {
			// 复制并更新面包屑路径
			let childrenBreadcrumb: any = [...breadcrumb, tmp]
			tmp.meta = { ...tmp.meta, breadcrumb: childrenBreadcrumb }
			// 删除 children 后先存储当前路由
			const { children, ...restRoute } = tmp
			res.push(restRoute)
			// 扁平化子路由
			res.push(...flatAsyncRoutes(children, childrenBreadcrumb))
		} else {
			// 没有子路由时，更新当前的面包屑路径
			tmp.meta = { ...tmp.meta, breadcrumb: [...breadcrumb, tmp] }
			res.push(tmp)
		}
	})
	return res
}
/**
 * 加载组件
 * @param componentName - 组件名称
 * @returns 组件
 */
function loadComponent(component: string) {
	return component ? modules[`../views/${component}/index.vue`] : () => import(`../layout/other/empty.vue`)
}
// 导出路由实例
export default router
